package com.zf.bm.common.core.sys.web;

import com.zf.bm.common.constant.Constant;
import com.zf.bm.common.core.factory.SignFactory;
import com.zf.bm.common.core.log.annotation.SysLog;
import com.zf.bm.common.core.shiro.realm.UserNamePasswordToken;
import com.zf.bm.common.core.shiro.utils.ShiroUtils;
import com.zf.bm.common.core.sys.entity.Login;
import com.zf.bm.common.core.sys.entity.User;
import com.zf.bm.common.core.sys.service.UserService;
import com.zf.bm.common.dto.ObjectConvert;
import com.zf.bm.common.core.sys.dto.LoginDTO;
import com.zf.bm.common.core.sys.dto.UsbKeyDTO;
import com.zf.bm.common.core.sys.dto.UserDTO;
import com.zf.bm.common.utils.CacheUtils;
import com.zf.bm.common.utils.SpringContextHolder;
import com.zf.bm.common.web.BaseController;
import com.zf.bm.config.ParamConfig;
import com.zf.bm.factory.SecretFactory;
import com.zf.bm.modules.system.entity.MonitorAuditLog;
import com.zf.bm.modules.system.service.MonitorAuditLogService;
import com.zf.bm.modules.system.utils.SystemUtils;
import com.zf.bm.service.ISecretService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;


/**
 * KEY登录Controller
 */
@RestController
@RequestMapping(value = "${adminPath}/key", method = {RequestMethod.GET, RequestMethod.POST})
@Slf4j
public class LoginKeyController extends BaseController {

    @Autowired
    private UserService userService;
    @Resource
    private SignFactory signFactory;
    @Resource
    private ParamConfig paramConfig;
    @Resource
    private SecretFactory secretFactory;

    /**
     * KEY登录
     *
     * @param login
     * @param response
     * @return
     */

    @SysLog("key登录")
    @PostMapping("/loginKey")
    public Result login(@RequestBody Login login, HttpServletRequest request, HttpServletResponse response) {
        try {
            User user = userService.getByLoginKey(login.getUsbKey());
            if (ValidatorUtil.isEmptyObj(user)) {
                return new Result(ResultStatus.FAIL.getCode(), "用户" + login.getUserName() + "未绑定key,请先绑定key");
            }
            UserUtils.userIpTable.put(user.getLoginName(), IPUtils.getRealIpAddress(request));
            login.setUserName(user.getLoginName());
            login.setPassword(Base64Util.decryption(user.getKeyPassword()));
            Subject subject = SecurityUtils.getSubject();
            UserNamePasswordToken userToken = new UserNamePasswordToken(login);
            subject.login(userToken);
            LoginDTO loginDTO = new LoginDTO();
            ObjectConvert<UserDTO> objectToDto = new ObjectConvert<>();
            UserDTO userDTO = new UserDTO();
            User account = UserUtils.getUser();
            if(ValidatorUtil.isNotEmptyObj(account)) {
                userDTO = objectToDto.toDto(account, userDTO);
                User u = userService.getByLoginName(account);
                String token = ShiroUtils.createToken(login);
                loginDTO.setToken(token);
                loginDTO.setUser(userDTO);
                response.setHeader(Constant.TOKEN, loginDTO.getToken());
                //更新用户登录新
                account.setLoginDate(new Date());
                account.setLoginIp(HttpUtils.getRemoteAddr());
                account.updateById();
                //用户登录成功清空密码错误次数
                CacheUtils.cleanPasswdRetryCount(u.getLoginName());
            }
            SystemUtils.saveSystemLog(login.getUserName(), "登录", 1, "用户KEY登录成功");
            //事件审计
            MonitorAuditLog monitorAuditLog = new MonitorAuditLog();
            monitorAuditLog.setOperateCommand("用户KEY登录");
            monitorAuditLog.setEventType("用户操作");
            monitorAuditLog.setOperateDescr("用户" + UserUtils.getUser().getName() + "登录成功");
            MonitorAuditLogService monitorAuditLogService = SpringContextHolder.getBean(MonitorAuditLogService.class);
            monitorAuditLogService.save(monitorAuditLog);
            return new Result(loginDTO);
        } catch (Exception e) {
            log.error("loginKey error:"+e);
            return new Result(ResultStatus.FAIL.getCode(), "key证书密码错误");
        }

    }

    @PostMapping("/checkSm3")
    public Result checkSm3(@RequestBody UsbKeyDTO usbKeyDTO) {
        // 获取原数据和签名数据
        ImmutablePair<String, String> data = signFactory.getSignService(usbKeyDTO.getType()).getSignData(usbKeyDTO.getId());
        if (StringUtil.isBlank(data.right)) {
            return new Result(ResultStatus.FAIL.getCode(), "暂无签名数据！");
        }

        try {
            ISecretService service = secretFactory.getSecretService(paramConfig.getType());

            // 验签
            boolean result = service.verifySign( data.left, data.right);
            if (result) {
                return new Result(ResultStatus.SUCCESS.getCode(), "数据完整！");
            }
        } catch (Exception e) {
            logger.error("checkSm3 error:" + e);
        }
        return new Result(ResultStatus.FAIL.getCode(), "数据不完整！");
    }
}
